package chapter01.part9;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 将流收集到 Map 中
 * 
 * @author insight
 * @since 2021/7/21
 */
public class CollectToMap {

    public static void main(String[] args) {
        Supplier<Stream<Person>> peoples = getPersonStream();

        /*
         * 使用 Collectors.toMap 两个函数参数 对应 key & value
         */
        Map<Integer, String> idToName = peoples.get().collect(
                Collectors.toMap(Person::getId, Person::getName)
        );
        System.out.println(idToName);
        
        // 对应实际值
        Map<Integer, Person> idToP = peoples.get().collect(
                Collectors.toMap(Person::getId, Function.identity())
        );
        System.out.println(idToP);
        
        // 处理冲突 使用第三个函数参数
        // 选择覆盖/保留
        Supplier<Stream<Locale>> locales = () -> Stream.of(
                Locale.getAvailableLocales()
        );

        Map<String, String> languageName = locales.get().collect(
                Collectors.toMap(
                        Locale::getDisplayLanguage,
                        locale -> locale.getDisplayLanguage(locale),
                        (v, newV) -> v
                )
        );
        System.out.println(languageName);

        // 选择合并
        // 假设一个国家有多个语言 合并成一个语言集
        Map<String, Set<String>> countryLangageNames = locales.get().collect(
                Collectors.toMap(
                        Locale::getDisplayCountry,
                        l -> Collections.singleton(l.getDisplayLanguage()),
                        (v, newV) -> {
                            HashSet<String> union = new HashSet<String>(v);
                            union.addAll(newV);
                            return union;
                        }
                )
        );
        System.out.println(countryLangageNames);
        
        // 还可以指定其他 Map
        idToP = peoples.get().collect(
                Collectors.toMap(
                        Person::getId,
                        Function.identity(),
                        (v, newV) -> { throw new IllegalStateException(); },
                        TreeMap::new
                )
        );
        System.out.println(idToP);
    }
    
    /**
     * 之前敲完没运行, 不知道流在使用终止操作后不能复用
     * 通过 Supplier 包装流, 间接复用
     */
    public static Supplier<Stream<Person>> getPersonStream() {
        return () -> Stream.of(
                new Person(1001, "Peter"),      
                new Person(1002, "Paul"),
                new Person(1003, "Peace")
        );
    }

    @Getter
    @ToString
    @AllArgsConstructor
    public static class Person {
        private int id;
        private String name;
    }
}